package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.enums.DelFlagStatus;
import com.ruoyi.common.enums.LiveStatus;
import com.ruoyi.common.enums.OrderStatus;
import com.ruoyi.common.enums.pay.TimeUnit;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MyListUtils;
import com.ruoyi.common.utils.exception.AjaxException;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.SysChannelMapper;
import com.ruoyi.system.mapper.SysUserChannelMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysControlService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.vo.OrderStatisticsRes;
import com.ruoyi.system.vo.SysControlRes;
import com.ruoyi.system.vo.WithdrawStatisticsRes;
import com.ruoyi.system.vo.req.SysOrderReq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysOrderMapper;
import com.ruoyi.system.service.ISysOrderService;
import com.ruoyi.common.core.text.Convert;

/**
 * 订单Service业务层处理
 *
 * @author Ericcc
 * @date 2021-03-01
 */
@Service
public class SysOrderServiceImpl implements ISysOrderService
{
    @Autowired
    private SysOrderMapper sysOrderMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysChannelMapper sysChannelMapper;

    @Autowired
    private SysUserChannelMapper sysUserChannelMapper;

    @Autowired
    private ISysControlService sysControlService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${my-gataway}")
    private String gataway;

    /**
     * 查询订单
     *
     * @param orderId 订单ID
     * @return 订单
     */
    @Override
    public SysOrder selectSysOrderById(Long orderId)
    {
        return sysOrderMapper.selectSysOrderById(orderId);
    }

    /**
     * 查询订单列表
     *
     * @param sysOrder 订单
     * @return 订单
     */
    @Override
    public List<SysOrder> selectSysOrderList(SysOrderReq sysOrder)
    {
        return sysOrderMapper.selectSysOrderList(sysOrder);
    }

    /**
     * 新增订单
     *
     * @param sysOrder 订单
     * @return 结果
     */
    @Override
    public String insertSysOrder(SysOrder sysOrder)
    {
        //检查用户状态
        SysUser sysUser = sysUserMapper.selectUserByUserCode(sysOrder.getUserCode());
        if (sysUser==null){
            throw new AjaxException("user is invalid");
        }
        //检查用户充值状态
        if (sysUser.getDepositStatus()!=LiveStatus.OK.getCode()){
            throw new AjaxException("pay forbbiden");
        }
        //检查父级状态
        if (sysUser.getParentId()!=null){
            SysUser agent = sysUserMapper.selectUserById(sysUser.getParentId());
            if (agent==null){
                throw new AjaxException("agent is invalid");
            }
            if (agent.getParentId()!=null){
                SysUser highAgent = sysUserMapper.selectUserById(agent.getParentId());
                if (highAgent==null){
                    throw new AjaxException("highAgent is invalid");
                }
            }
        }

        //检查用户通道状态
        SysUserChannel sysUserChannel = sysUserChannelMapper.selectSysUserChannelById(sysUser.getUserId());
        if (sysUserChannel==null){
            throw new AjaxException("user's channel error");
        }
        //检查通道状态
        SysChannel sysChannel = sysChannelMapper.selectSysChannelById(sysUserChannel.getChannelId());
        if (sysChannel==null){
            throw new AjaxException("channel error");
        }
        if (sysChannel.getStatus()==LiveStatus.DISABLE.getCode()){
            throw new AjaxException("channel is close");
        }

        //检查用户风控状态
        SysControlRes sysControl = sysControlService.selectSysControlByUser(sysUser.getUserId());
        checkContrl(sysControl,sysOrder);
        //检查通道风控状态
        SysControlRes sysControl2 = sysControlService.selectSysControlByChannel(sysUserChannel.getChannelId());
        checkContrl(sysControl2,sysOrder);

        //判断订单号是否重复(数据库层面)
        int count = sysOrderMapper.checkByOrderChildCode(sysOrder.getOrderChildCode());
        if (count > 0) {
            throw new AjaxException("Duplicate order number");
        }
        //判断订单号是否重复(缓存 避免高并发下数据层面筛选不了)
        String key = "checkPay_" + sysOrder.getOrderChildCode();
        boolean flag = stringRedisTemplate.getConnectionFactory().getConnection().setNX(key.getBytes(), sysOrder.getOrderChildCode().getBytes());
        if (!flag) {
            throw new AjaxException("Duplicate order number");
        }
        stringRedisTemplate.expire(key, 180, java.util.concurrent.TimeUnit.SECONDS);

        //计算费率
        BigDecimal rate = sysUserChannel.getUserChannelRate1();
        sysOrder.setOrderCharge(sysOrder.getOrderAmount().multiply(rate).add(sysUserChannel.getUserChannelFee()));
        sysOrder.setOrderLastAmount(sysOrder.getOrderAmount().subtract(sysOrder.getOrderCharge()));
        //设置订单号
        sysOrder.setOrderCode(sysOrder.getOrderChildCode());
        //用户信息
        sysOrder.setUserId(sysUser.getUserId());
        //通道信息
        sysOrder.setChannelId(sysUserChannel.getChannelId());
        sysOrder.setChannelName(sysChannel.getChannelName());
        //订单状态
        sysOrder.setStatus(OrderStatus.DISABLE.getCode());
        //订单备注
        sysOrder.setOrderRemark("测试订单");
        sysOrder.setCreateTime(new Date());
        //
        sysOrder.setNotifyUrl(sysChannel.getChannelNotifyurl());
        try {
            sysOrderMapper.insertSysOrder(sysOrder);
        }catch (Exception e){
            throw new AjaxException("system error,please try again");
        }finally {
            stringRedisTemplate.delete(key);
        }
        return "getLink/"+sysOrder.getOrderId();
    }

    /**
     * 修改订单
     *
     * @param sysOrder 订单
     * @return 结果
     */
    @Override
    public int updateSysOrder(SysOrder sysOrder)
    {
        return sysOrderMapper.updateSysOrder(sysOrder);
    }

    /**
     * 删除订单对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteSysOrderByIds(String ids)
    {
        return sysOrderMapper.deleteSysOrderByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除订单信息
     *
     * @param orderId 订单ID
     * @return 结果
     */
    @Override
    public int deleteSysOrderById(Long orderId)
    {
        return sysOrderMapper.deleteSysOrderById(orderId);
    }

    /**
     * 查询条件和单位时间查询订单金额统计
     * @param sysOrder 订单
     * @return
     */
    @Override
    public BigDecimal selectSysOrderAmount(SysOrderReq sysOrder,Date beginTime) {
        sysOrder.setBeginDate(beginTime);
        return sysOrderMapper.selectSysOrderAmount(sysOrder);
    }

    @Override
    public OrderStatisticsRes selectSysOrderStatistics(SysOrderReq sysOrder) {
        return sysOrderMapper.selectSysOrderStatistics(sysOrder);
    }

    @Override
    public List<SysOrder> selectSysAgentOrder(SysOrderReq sysOrder,long parentId) {
        Map map = new HashMap();
        map.put("parentId",parentId);
        sysOrder.setParams(map);
        return sysOrderMapper.selectSysAgentOrder(sysOrder);
    }

    @Override
    public OrderStatisticsRes selectAgentSysOrderStatistics(SysOrderReq sysOrder) {
        return sysOrderMapper.selectAgentSysOrderStatistics(sysOrder);
    }

    @Override
    public BigDecimal selectAgentSysOrderAmount(SysOrderReq sysOrder, Date beginTime) {
        sysOrder.setBeginDate(beginTime);
        return sysOrderMapper.selectAgentSysOrderAmount(sysOrder);
    }

    @Override
    public List<SysOrder> selectSysHighAgentOrder(SysOrderReq sysOrder, Long parentId) {
        Map map = new HashMap();
        map.put("parentId",parentId);
        sysOrder.setParams(map);
        return sysOrderMapper.selectSysHighAgentOrder(sysOrder);
    }

    /**
     * 获取高级代理底下商户订单统计
     * @param sysOrder
     * @return
     */
    @Override
    public OrderStatisticsRes selectHighAgentSysOrderStatistics(SysOrderReq sysOrder) {
        return sysOrderMapper.selectHighAgentSysOrderStatistics(sysOrder);
    }

    /**
     * 获取代高级理底下商户单位时间内金额统计
     * @param sysOrder
     * @param beginTime
     * @return
     */
    @Override
    public BigDecimal selectHighAgentSysOrderAmount(SysOrderReq sysOrder, Date beginTime) {
        sysOrder.setBeginDate(beginTime);
        return sysOrderMapper.selectHighAgentSysOrderAmount(sysOrder);
    }

    /**
     * 风控校验规则
     */
    public void checkContrl(SysControlRes sysControl,SysOrder sysOrder){
        //风控状态开启的情况下
        if (sysControl.getControlStatus()==LiveStatus.OK.getCode()) {
            //是否大于风控最小金额
            if (sysOrder.getOrderAmount().compareTo(sysControl.getMinBalance()) < 0) {
                throw new BusinessException("pay is a minimum of " + sysControl.getMinBalance().setScale(0));
            }
            //是否小于风控最大金额
            if (sysOrder.getOrderAmount().compareTo(sysControl.getMaxBalance()) > 0) {
                throw new BusinessException("the largest balance is " + sysControl.getMaxBalance().setScale(0));
            }
            //是否在风控允许交易的时间范围内
            Date startTime = DateUtil.parse(sysControl.getStartTime());
            Date endTime = DateUtil.parse(sysControl.getEndTime());
            Date dateTime = new Date();
            if (startTime.getTime()!=endTime.getTime()) {
                if (dateTime.getTime() < startTime.getTime()) {
                    throw new BusinessException("pay is start at about " + startTime);
                }
                if (dateTime.getTime() > endTime.getTime()) {
                    throw new BusinessException("pay is end at about " + endTime);
                }
            }
            //是否超过风控总金额
            BigDecimal todayBalance = sysOrderMapper.getTimeRangeBalance(DateUtils.getNowDay(1));
            if (todayBalance==null){
                todayBalance = BigDecimal.ZERO;
            }
            if (todayBalance.add(sysOrder.getOrderAmount()).compareTo(sysControl.getTodayBalance())>0){
                throw new BusinessException("That's more than today's maximum balance");
            }
            /*------------查询单位时间限制-------------*/
            if (sysControl.getTimeRange()>0) {
                long time = 0L;
                //以秒为限制
                if (sysControl.getTimeUnit() == TimeUnit.SECOND.getCode()) {
                    time = DateUtils.getNowSecond(sysControl.getTimeRange().intValue());
                }
                //以分为单位
                else if (sysControl.getTimeUnit() == TimeUnit.MINUTE.getCode()) {
                    time = DateUtils.getNowMinute(sysControl.getTimeRange().intValue());
                }
                //以小时为单位
                else if (sysControl.getTimeUnit() == TimeUnit.HOUR.getCode()) {
                    time = DateUtils.getNowHour(sysControl.getTimeRange().intValue());
                }
                //以天为单位
                else if (sysControl.getTimeUnit() == TimeUnit.DAY.getCode()) {
                    time = DateUtils.getNowDay(sysControl.getTimeRange().intValue());
                }
                //BUG
                else {
                    throw new BusinessException("time-range error!please concact the admin");
                }
                BigDecimal timeBalance = sysOrderMapper.getTimeRangeBalance(time);
                if (timeBalance==null){
                    timeBalance = BigDecimal.ZERO;
                }
                if (timeBalance.add(sysOrder.getOrderAmount()).compareTo(sysControl.getTimeBalance())>0){
                    throw new BusinessException("exceed the limit balance about timeunit:SECOND;please try later");
                }
                if (sysOrderMapper.getTimeRangeSize(time)+1>sysControl.getTimeSize()){
                    throw new BusinessException("exceed the limit size about timeunit:SECOND;please try later");
                }
            }
        }
    }
}
